<template>
  <div class="global-uploader">
    <uploader
      ref="uploader"
      :key="uploader_key"
      :options="options"
      :autoStart="false"
      class="uploader-example"
      @file-success="onFileSuccess"
      @file-added="onFileAdded"
      @file-error="onFileError"
    >
      <uploader-unsupport></uploader-unsupport>

      <uploader-btn :single="true" ref="uploadfileBtn" class="global-uploader-file-btn"></uploader-btn>
      <uploader-btn
        :single="true"
        :directory="true"
        ref="uploaddirBtn"
        class="global-uploader-dir-btn"
      ></uploader-btn>
      <uploader-list v-show="panelShow">
        <div class="file-panel" slot-scope="props" :class="{'collapse': collapse}">
          <div class="file-title">
            <h2>上传文件</h2>
            <div class="operate">
              <el-button
                :class="collapse?'el-icon-full-screen':'el-icon-minus'"
                @click="fileListShow"
                type="text"
                :title="collapse ? '展开':'折叠' "
              ></el-button>
              <el-button class="el-icon-close" @click="close" type="text" title="关闭"></el-button>
            </div>
          </div>

          <ul class="file-list">
            <li v-for="file in props.fileList" :key="file.id">
              <uploader-file :class="'file_' + file.id" ref="files" :file="file" :list="true"></uploader-file>
            </li>
            <div class="no-file" v-if="!props.fileList.length">..(｡•ˇ‸ˇ•｡)… 暂无待上传文件</div>
          </ul>
        </div>
      </uploader-list>
    </uploader>
  </div>
</template>

<script>
import { simpleUploadURL } from "@/utils/global.js";
import SparkMD5 from "spark-md5";
import { fileAPI } from "@/utils/api.js";
import $ from "jquery";
import Bus from "@/upload/bus.js";
import { mapState, mapGetters, mapMutations } from "vuex";
export default {
  data() {
    return {
      uploader_key: new Date().getTime(), //这个用来刷新组件--解决不刷新页面连续上传的缓存上传数据（注：每次上传时，强制这个值进行更改---根据自己的实际情况重新赋值）
      options: {
        target: simpleUploadURL, //后台接收文件夹数据的接口
        forceChunkSize: true,
        testChunks: false, //是否测试分片
        /*  checkChunkUploadedByResponse: function(chunk, response) {
          let objMessage = JSON.parse(response);
          console.log(chunk, objMessage);
          if (objMessage.code != 0) {
            return true;
          }
          return false;
        }, */
        fileParameterName: "upfile",
        maxChunkRetries: 3,
        headers: {
          Authorization: "bearer" + localStorage.getItem("token")
        },
        query() {},
        parseTimeRemaining: function(timeRemaining, parsedTimeRemaining) {
          return parsedTimeRemaining
            .replace(/\syears?/, "年")
            .replace(/\days?/, "天")
            .replace(/\shours?/, "小时")
            .replace(/\sminutes?/, "分钟")
            .replace(/\sseconds?/, "秒");
        }
      },
      panelShow: false, //选择文件后，展示上传panel
      collapse: false
    };
  },
  props: {
    msg: String
  },
  computed: {
    ...mapState({ nav: state => state.files.nav }),
    ...mapGetters({ rootPath: "getRootPath" }),
    //Uploader实例
    uploader() {
      return this.$refs.uploader.uploader;
    }
  },
  /* watch: {
    panelShow(newValue) {
      this.uploadShow = newValue;
      if (newValue) {
        $(".global-uploader-btn").click();
      }
    }
  }, */
  mounted() {
    Bus.$on("openUploader", query => {
      if (this.$refs[`upload${query.type}Btn`]) {
        $(`.global-uploader-${query.type}-btn`).click();
      }
    });
  },
  methods: {
    /**
     * 文件上传成功回调
     */
    onFileSuccess: function(rootFile, file, response, chunk) {
      fileAPI.upload
        .combine({
          uuid: this.uuid
        })
        .then(res => {
          // 文件合并成功
          console.log(res);
          $(".uploader-file-remove").show();
          /* this.$message({
            message: "文件上传成功",
            type: "success",
            duration: 1000
          }); */
          this.addFile(file);
        })
        .catch(e => {});
    },
    /**
     * 合并完成后加入到服务器目录
     */
    addFile(file) {
      Bus.$emit("onAddFile", {
        md5: file.uniqueIdentifier,
        name: file.name,
        size: file.size,
        tag: this.uploader.opts.query.uuid
      });
    },
    /**
     * 获取文件uuid 同步请求
     */
    async getUUID() {
      try {
        let res = await fileAPI.upload.getUUID();
        this.uuid = res.data.uuid;
      } catch (err) {
        this.error(err + "uuid err");
      }
    },
    /**
     * 计算md5，实现断点续传及秒传
     * @param file
     */
    computeMD5(file) {
      //大文件的md5计算时间比较长，显示个进度条
      const loading = this.$loading({
        lock: true,
        text: "正在计算MD5",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)"
      });
      let fileReader = new FileReader();
      let time = new Date().getTime();
      let blobSlice =
        File.prototype.slice ||
        File.prototype.mozSlice ||
        File.prototype.webkitSlice;
      let currentChunk = 0;
      const chunkSize = 10 * 1024 * 1000;
      let chunks = Math.ceil(file.size / chunkSize);
      let spark = new SparkMD5.ArrayBuffer();
      file.pause();

      loadNext();

      fileReader.onload = e => {
        spark.append(e.target.result);
        if (currentChunk < chunks) {
          currentChunk++;
          loadNext();
          // 实时展示MD5的计算进度
          /*  this.$nextTick(() => {
            console.log(
              "校验MD5 " + ((currentChunk / chunks) * 100).toFixed(0) + "%"
            );
          }); */
        } else {
          let md5 = spark.end();
          loading.close();
          this.computeMD5Success(md5, file);
          /* console.log(
            `MD5计算完毕：${file.name} \nMD5：${md5} \n分片：${chunks} 大小:${
              file.size
            } 用时：${new Date().getTime() - time} ms`
          ); */
        }
      };
      fileReader.onerror = function() {
        this.error(`文件${file.name}读取出错，请检查该文件`);
        loading.close();
        file.cancel();
      };
      function loadNext() {
        let start = currentChunk * chunkSize;
        let end =
          start + chunkSize >= file.size ? file.size : start + chunkSize;
        fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
      }
    },

    /**
     *计算文件MD5成功，并添加自定义参数
     */
    computeMD5Success(md5, file) {
      Object.assign(this.uploader.opts, {
        query: {
          uuid: this.uuid
        }
      });
      file.uniqueIdentifier = md5; //把md5值作为文件的识别码
      file.resume(); //开始上传
    },
    /**
     * 添加文件后触发
     * @param file
     * @param event
     */
    async onFileAdded(file, event) {
      console.log(file);
      this.panelShow = true;
      await this.getUUID();
      this.computeMD5(file);
    },
    /**
     * 文件上传失败回调
     */
    onFileError(rootFile, file, response, chunk) {
      this.$message({
        message: "上传失败",
        type: "error"
      });
    },

    fileListShow() {
      let $uploader = $(".uploader-example");
      let $list = $(".global-uploader .file-list");
      if ($list.is(":visible")) {
        $list.slideUp();
        $uploader.animate({ width: "80px", right: "0", bottom: "50px" }, 250);
        this.collapse = true;
      } else {
        $uploader.animate(
          { width: "520px", right: "15px", bottom: "10px" },
          250
        );
        $list.slideDown();
        this.collapse = false;
      }
    },
    close() {
      this.uploader.cancel();
      this.panelShow = false;
    },
    destroyed() {
      Bus.$off("openUploader");
    }
  }
};
</script>

<style lang="scss" scoped>
.global-uploader {
  position: fixed;
  z-index: 20;
  right: 15px;
  bottom: 10px;

  .uploader-example {
    width: 520px;
  }
  .file-panel {
    background-color: #fff;
    border: 1px solid #e2e2e2;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
    .file-title {
      display: flex;
      height: 40px;
      line-height: 40px;
      padding: 0 15px;
      border-bottom: 1px solid #ddd;
      .operate {
        flex: 1;
        text-align: right;
      }
    }
    .file-list {
      position: relative;
      height: 150px;
      overflow-x: hidden;
      overflow-y: auto;
      background-color: #fff;
      font-size: 12px;
      > li {
        background-color: #fff;
      }
      /deep/.uploader-file-name {
        width: 42%;
      }
      /deep/.uploader-file-meta {
        width: 0;
      }
      /deep/.uploader-file-status {
        width: 35%;
        text-align: center;
        text-indent: 0;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    }
    &.collapse {
      .file-title {
        background-color: #e7ecf2;
        h2 {
          display: none;
        }
      }
    }
  }
  .no-file {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 16px;
  }
  /deep/.uploader-file-icon {
    &:before {
      content: "" !important;
    }
    &[icon="image"] {
      background: url("../../assets/file_icons/Png.png");
    }
    &[icon="video"] {
      background: url("../../assets/file_icons/Video.png");
    }
    &[icon="document"] {
      background: url("../../assets/file_icons/File.png");
    }
  }
  /deep/.uploader-file-actions > span {
    margin-right: 6px;
  }
}
/* 隐藏上传按钮 */
.uploader-btn.global-uploader-file-btn,
.uploader-btn.global-uploader-dir-btn {
  position: absolute;
  clip: rect(0, 0, 0, 0);
}
</style>